const axios = require('axios');
const qs = require('qs');

const SocksProxyAgent = require('socks-proxy-agent');
const httpsAgent = new SocksProxyAgent('socks5://127.0.0.1:1080');

axios.interceptors.request.use(function (config) {
  config.proxy = false;
  config.httpAgent = httpsAgent;
  config.httpsAgent = httpsAgent;
  return config;
});


const refreshTokenURI = 'https://www.googleapis.com/oauth2/v4/token';
const uploadExistingURI = id => `https://www.googleapis.com/upload/chromewebstore/v1.1/items/${id}`;
const publishURI = (id, target) => (
  `https://www.googleapis.com/chromewebstore/v1.1/items/${id}/publish?publishTarget=${target}`
);

const requiredFields = [
  'extensionId', 'clientId', 'clientSecret', 'refreshToken'
];

class APIClient {
  constructor(opts) {
    requiredFields.forEach(field => {
      if (!opts[field]) {
        throw new Error(`Option "${field}" is required`);
      }

      this[field] = opts[field];
    });
  }

  uploadExisting(readStream, token) {
    if (!readStream) {
      return Promise.reject(new Error('Read stream missing'));
    }

    const { extensionId } = this;
    const eventualToken = token ? Promise.resolve(token) : this.fetchToken();

    // eslint-disable-next-line no-shadow
    return eventualToken.then(token => {
      return axios({
        method: 'PUT',
        url: uploadExistingURI(extensionId),
        headers: this._headers(token),
        data: readStream
      }).then(this._extractBody);
    });
  }

  publish(target = 'default', token) {
    const { extensionId } = this;
    const eventualToken = token ? Promise.resolve(token) : this.fetchToken();

    // eslint-disable-next-line no-shadow
    return eventualToken.then(token => {
      return axios({
        url: publishURI(extensionId, target),
        method: 'POST',
        headers: this._headers(token)
      }).then(this._extractBody);
    });
  }

  fetchToken() {
    const { clientId, clientSecret, refreshToken } = this;

    return axios({
      url: refreshTokenURI,
      method: 'POST',
      headers: { 'content-type': 'application/x-www-form-urlencoded' },
      data: qs.stringify({
        client_id: clientId,
        client_secret: clientSecret,
        refresh_token: refreshToken,
        grant_type: 'refresh_token'
      })
    }).then(this._extractBody).then(({ access_token }) => access_token);
  }

  // eslint-disable-next-line class-methods-use-this
  _headers(token) {
    return {
      Authorization: `Bearer ${token}`,
      'x-goog-api-version': '2'
    };
  }

  // eslint-disable-next-line class-methods-use-this
  _extractBody({ data }) {
    return data;
  }
}


module.exports = function (...args) {
  return new APIClient(...args);
};
